﻿using MyWoW.FiniteStateMachine;
using SBSimpleLib.Utils;
using ShadowBot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SBSimpleLib
{
    public abstract class BaseEntryPoint
    {
        // Static members
        private static String TAG = "BEP";
        private static BaseEntryPoint entryPoint = null;
        public static BaseEntryPoint EntryPoint
        {
            get { return entryPoint; }
            protected set
            {
                entryPoint = value;
                Logger.info(TAG, entryPoint.BotName + " EntryPoint: " + entryPoint.GetType().FullName);
            }
        }
        private Ticker ticker = null;


        private Form mainForm = null;
        private bool isEnabled = false;
        private String botName = "DefaultBotName";

        private List<KTState> botStatesAdded = new List<KTState>();
        private List<State> sbStatesRemoved = new List<State>();
        private List<String> botStatesToRemove = new List<String>();


        public bool IsEnabled 
        { 
            get { return isEnabled; } 
            set {
                Logger.info(TAG, BotName + " enabled: " + isEnabled);
                isEnabled = value; 
            } 
        }
        public String BotName { get { return botName; }  }
        public Form MainForm { get { return mainForm; } protected set { mainForm = value; } }
        public Ticker Ticker { 
            get { return ticker; } 
            set {
                ticker = value;
                Logger.debug(TAG, "setting ticker: " + ticker.NumSeconds);
            }
        }
        private Thread guiUpdater = null;

        

        public BaseEntryPoint(String name)
        {
            botName = name;
            Logger.info(TAG, "Creating " + BotName + " from " + GetType().FullName);
        }





        public void doPlugin_Settings()
        {
            Logger.debug(TAG, BotName + " doPlugin_Settings");
        }

        #region add/remove states
        protected void addState(KTState state)
        {
            botStatesAdded.Add(state);
        }


        public static void RemoveState(String state)
        {
            EntryPoint.removeState(state);
        }

        protected void removeState(String state)
        {
            Logger.debug(TAG, " removing " + state + " from states");

            State ret = null;

            int indexToDelete = -1;
            int cont = 0;
            foreach (MyWoW.FiniteStateMachine.State currentState in API.Bot.Overrides.FiniteStateMachine.Engine.States)
	        {
                if (currentState.DisplayName == state)
                {
                    indexToDelete = cont;
                    break;
                }
                cont++;
	        }

            if (indexToDelete != -1)
            {
                ret = API.Bot.Overrides.FiniteStateMachine.Engine.States[indexToDelete];
                sbStatesRemoved.Add(ret);
                Logger.debug(TAG, " removed " + state + " from states at index: " + indexToDelete);
                API.Bot.Overrides.FiniteStateMachine.Engine.States.RemoveAt(indexToDelete);
            }
            
        }
        #endregion

        #region Enable/Disable


        public void doPlugin_OnDisable()
        {
            Logger.debug(TAG, BotName + " doPlugin_OnDisable");
            

            Logger.info(TAG, "De-Registering on Start/Stop Events.");
            API.Bot.Events.OnBotStart -= new API.Bot.Events.OnBotStartEventHandler(EntryPoint.doOnBotStart);
            API.Bot.Events.OnBotStop -= new API.Bot.Events.OnBotStopEventHandler(EntryPoint.doOnBotStop);


            if (MainForm != null && MainForm.Visible)
            {
                MainForm.Visible = false;
            }

            IsEnabled = false;

            Logger.info(TAG, BotName + " disabled.");
        }

        public void doPlugin_OnEnable()
        {
            Logger.debug(TAG, BotName + " doPlugin_OnEnable");

            // Register on start / stop events
            Logger.info(TAG, "Registering on Start/Stop Events.");
            API.Bot.Events.OnBotStart += new API.Bot.Events.OnBotStartEventHandler(EntryPoint.doOnBotStart);
            API.Bot.Events.OnBotStop += new API.Bot.Events.OnBotStopEventHandler(EntryPoint.doOnBotStop);

            // Show the form
            if (MainForm  != null && !MainForm.Visible)
            {
                MainForm.Show(); ;

            }

            Logger.info(TAG, BotName + " enabled.");

        }

        

        #endregion
        
        #region Start/Stop

        public abstract void doOnBotPreStart(object sender, EventArgs args);
        public abstract void doOnBotPreStop(object sender, EventArgs args);

        public void doOnBotStart(object sender, EventArgs args)
        {
            
            botStatesAdded = new List<KTState>();
            sbStatesRemoved = new List<State>();
            botStatesToRemove = new List<String>();

            if (Ticker != null)
            {
                Logger.info(TAG, "Starting UI Updater Thread.");
                guiUpdater = new Thread(new ThreadStart(ticker.run));
                guiUpdater.Name = "UI Updater";
                guiUpdater.Start();
            }

            doOnBotPreStart(sender, args);

            foreach (KTState state in botStatesAdded)
            {
                Logger.debug(TAG, " restoring " + state.DisplayName + " to states");
                API.Bot.Overrides.FiniteStateMachine.Engine.AddState(state);
            }

            API.Bot.Overrides.FiniteStateMachine.Engine.States.Sort();

            Utilities.dumpStates(TAG);

            IsEnabled = true;

            Logger.info(TAG, BotName + " started.");

        }

        public void doOnBotStop(object sender, EventArgs args)
        {

            if (ticker != null)
            {
                Logger.info(TAG, "Stoping UI Updater Thread.");
                ticker.requestStop();
            }


            doOnBotPreStop(sender, args);


            foreach (State state in sbStatesRemoved)
            {
                Logger.debug(TAG, " getting back " + state.DisplayName + " to states");
                API.Bot.Overrides.FiniteStateMachine.Engine.AddState(state);
            }

            IsEnabled = false;

            Logger.info(TAG, BotName + " stoped.");
        }

    #endregion


    }
}
